﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Activation;
using JXT.PrimaryKey.Batman.Core.Extensions;
using JXT.PrimaryKey.Batman.Core.WcfService;
using JXT.PrimaryKey.Batman.Domain.Models;
using JXT.PrimaryKey.Batman.Domain.UserSystem.Models;
using JXT.PrimaryKey.Batman.Domain.UserSystem.Services;
using JXT.PrimaryKey.Batman.WcfService.Services.Extensions;
using JXT.PrimaryKey.Batman.WcfService.Interfaces;
using JXT.PrimaryKey.Batman.WcfService.Services.Converters.UserSystem;
using DTO = JXT.PrimaryKey.Batman.WcfService.Models.UserSystem;

namespace JXT.PrimaryKey.Batman.WcfService.Services
{
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class WcfUserService : WcfWebServiceBase, IUser
    {
        [WcfAuthentication]
        public List<DTO.UserIdentity> GetUserIdentityList()
        {
            var list = LoadService<IUserIdentityService>().GetList();
            return UserIdentityConverter.Instanse.ConvertEnumerable(list).ToList();
        }

        [WcfAuthentication]
        public DTO.User GetSingle(string id)
        {
            int idInt32 = id.ToInt32();
            var specification = SpecificationFactory.CreateSpecification<User>();
            specification.And(e => e.Id == idInt32);
            var entity = LoadService<IUserService>().GetSingle(specification);
            if (entity != null)
            {
                entity.Detail = LoadService<IUserService>().GetDetail(entity);
                entity.Status = LoadService<IUserService>().GetStatus(entity);
            }
            return UserConverter.Instanse.Convert(entity);
        }

        [WcfAuthentication]
        public DTO.BasicUser Register(DTO.RegisterUser user)
        {
            if (user == null)
                throw new ArgumentNullException("user");
            IEnumerable<Role> roles;
            if (user.RoleIdArray == null)
                roles = null;
            else
                roles = LoadService<IRoleService>().GetList().Where(obj1 => user.RoleIdArray.Any(obj2 => obj2 == obj1.Id));
            var sysUser = LoadService<IUserService>().Register(user.Name, user.Mail, user.Password.ToMd5(), user.RealName, (Gender)((byte)user.Gender), user.Identity, user.RegisterIp, roles);
            DTO.BasicUser result = new DTO.BasicUser();
            result.FromDomainModel(sysUser);
            return result;
        }

        [WcfAuthentication]
        public DTO.User GetSingleByName(string name)
        {
            var specification = SpecificationFactory.CreateSpecification<User>();
            specification.And(e => e.Name == name);
            var entity = LoadService<IUserService>().GetSingle(specification);
            if (entity != null)
            {
                entity.Detail = LoadService<IUserService>().GetDetail(entity);
                entity.Status = LoadService<IUserService>().GetStatus(entity);
            }
            return UserConverter.Instanse.Convert(entity);
        }

        [WcfAuthentication]
        public DTO.User GetSingleByMail(string mail)
        {
            var specification = SpecificationFactory.CreateSpecification<User>();
            specification.And(e => e.Mail == mail);
            var entity = LoadService<IUserService>().GetSingle(specification);
            if (entity != null)
            {
                entity.Detail = LoadService<IUserService>().GetDetail(entity);
                entity.Status = LoadService<IUserService>().GetStatus(entity);
            }
            return UserConverter.Instanse.Convert(entity);
        }

        [WcfAuthentication]
        public void ChangePassword(DTO.ChangedPassword password)
        {
            if (password == null)
                throw new ArgumentNullException("password");
            if (String.IsNullOrWhiteSpace(password.Password))
                throw new ArgumentNullException("password.Password");
            var specification = SpecificationFactory.CreateSpecification<User>();
            specification.And(e => e.Id == password.UserId);
            var entity = LoadService<IUserService>().GetSingle(specification);
            if (entity == null)
                return;
            entity.Password = password.Password.ToMd5();
            LoadService<IUserService>().Save(entity);
        }

        [WcfAuthentication]
        public void UpdateDetail(DTO.UserDetail detail)
        {
            var specification = SpecificationFactory.CreateSpecification<User>();
            specification.And(e => e.Id == detail.UserId);
            var user = LoadService<IUserService>().GetSingle(specification);
            if (user == null)
                throw new ObjectNotFoundException("user");
            var sysDetail = UserDetailConverter.Instanse.ConvertBack(detail);
            LoadService<IUserService>().UpdateDetail(user, sysDetail);
        }

        [WcfAuthentication]
        public void UpdateLoginStatus(DTO.UpdatedStatus status)
        {
            if (status == null)
                throw new ArgumentNullException("status");
            if (String.IsNullOrWhiteSpace(status.LoginIp))
                throw new ArgumentNullException("status.LoginIp");
            var specification = SpecificationFactory.CreateSpecification<User>();
            specification.And(e => e.Id == status.UserId);
            var entity = LoadService<IUserService>().GetSingle(specification);
            if (entity != null)
            {
                LoadService<IUserService>().UpdateStatus(entity, status.LoginIp);
            }
        }

        [WcfAuthentication]
        public bool ExistsName(string name)
        {
            var specification = SpecificationFactory.CreateSpecification<User>();
            specification.And(e => e.Name == name);
            return LoadService<IUserService>().Exists(specification);
        }

        [WcfAuthentication]
        public bool ExistsMail(string mail)
        {
            var specification = SpecificationFactory.CreateSpecification<User>();
            specification.And(e => e.Mail == mail);
            return LoadService<IUserService>().Exists(specification);
        }

        public string SystemLogin(string id, string key)
        {
            var status = LoadService<ISystemUserService>().Login(id, key, OperationContext.Current.GetClientIp());
            if (status == null)
                return null;
            else
                return status.DynamicKey;
        }

        public void SystemLogout(string id, string key)
        {
            LoadService<ISystemUserService>().Logout(id, key, OperationContext.Current.GetClientIp());
        }

        [WcfAuthentication]
        public DTO.LoginUser CheckLoginStatus(string token)
        {
            var entity = LoadService<IUserService>().GetLoginSingle(token);
            return LoginUserConverter.Instanse.Convert(entity);
        }

        [WcfAuthentication]
        public List<DTO.Role> GetRoleList()
        {
            var list = LoadService<IRoleService>().GetList();
            return RoleConverter.Instanse.ConvertEnumerable(list).ToList();
        }

        [WcfAuthentication]
        public void Logout(string token)
        {
            LoadService<IUserService>().Logout(token, ServiceEnvironment.GetAuthenticationId());
        }
    }
}
